package com.geotmt.billingcenter.modules.statis.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.geotmt.billingcenter.common.entry.ConsumeStatisEntry;
import com.geotmt.billingcenter.common.exception.MyException;
import com.geotmt.billingcenter.common.utils.GeoDateUtils;
import com.geotmt.billingcenter.common.vo.consume.ConsumeHisVo;
import com.geotmt.billingcenter.common.vo.consume.ConsumeStatisVo;
import com.geotmt.billingcenter.common.vo.params.ParamsConsume;
import com.geotmt.billingcenter.common.vo.params.RuleVo;
import com.geotmt.billingcenter.modules.consume.service.ConsumeService;
import com.geotmt.billingcenter.modules.designmode.service.RulesStrategy;
import com.geotmt.billingcenter.modules.link.service.LinkService;
import com.geotmt.billingcenter.modules.statis.mapper.ConsumeStatisMapper;
import com.geotmt.billingcenter.modules.statis.service.ConsumeStatisService;
import com.github.pagehelper.PageHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;

/**
 * @Description 消耗统计
 * @Author      yanghanwei
 * @Mail        yanghanwei@geotmt.com
 * @Date        2019/3/27 18:19
 * @Version     v1
 **/
@Service
public class ConsumeStatisServiceImpl extends AbstarctService implements ConsumeStatisService {

    private static final Logger logger = LoggerFactory.getLogger(ConsumeStatisServiceImpl.class);

    private static final int BATCH_NUM = 1000;

    @Resource
    private ConsumeStatisMapper consumeStatisMapper;

    @Resource
    private LinkService linkService;

    @Override
    public List<ConsumeStatisVo> consumeStatisList(ParamsConsume obj) {
        logger.info("最细维度消耗统计List Service");
        this.insertPage(obj);
        return consumeStatisMapper.consumeStatisList(obj);
    }

    @Override
    public ConsumeStatisVo consumeStatisTotal(ParamsConsume obj) {
        logger.info("最细维度消耗统计List的总计 Service");
        return consumeStatisMapper.consumeStatisTotal(obj);
    }

    @Override
    public ConsumeStatisVo hisConsumeStatis(ParamsConsume obj) {
        logger.info("获取消耗历史数量 Service");
        return consumeStatisMapper.hisConsumeStatis(obj);
    }

    @Override
    public List<ConsumeStatisVo> consumeStatisCompanyList(ParamsConsume obj) {
        logger.info("精确到客户维度消耗统计List Service");
        this.insertPage(obj);
        return consumeStatisMapper.consumeStatisCompanyList(obj);
    }

    @Override
    public int deleteConsumeStatis(String dayFlag) {
        logger.info("精确到客户维度消耗统计List Service");
        return consumeStatisMapper.deleteConsumeStatis(dayFlag, new Date());
    }

    @Override
    public int deleteConsumeStatis2(String startDay, String endDay) {
        logger.info("删除某段时间的消耗统计 Service");
        return consumeStatisMapper.deleteConsumeStatis2(startDay, endDay, new Date());
    }

    @Override
    public int updateConsumeStatis(String startDay, String endDay, Integer id) {
        logger.info("更新统计报表中的相关维度id信息 Service");
        return consumeStatisMapper.updateConsumeStatis(startDay, endDay, id);
    }

    @Override
    public int updateConsumeMoney(Integer cuserId, Integer interfaceId, String dayFlag, Double money) {
        return consumeStatisMapper.updateConsumeMoney(cuserId, interfaceId, dayFlag, money);
    }

    @Override
    public int updateConsumeMoney(Integer cuserId, String interfaceType, String dayFlag, Double money) {
        return consumeStatisMapper.updateConsumeMoney2(cuserId, interfaceType, dayFlag, money);
    }

    @Override
    public void batchInsertStatis(List<ConsumeStatisEntry> consumeStatisList) {
        int size = consumeStatisList.size();
        int num = consumeStatisList.size() / BATCH_NUM  + 1;
        for(int i= 0; i<num; i++){
            // 2 切分并批量插入mysql
            List<ConsumeStatisEntry> subConsumeStatisList = consumeStatisList.subList(this.getStartNum(i), this.getEndNum(i, num, size));
            consumeStatisMapper.batchInsertStatis(subConsumeStatisList);
        }
    }

    @Async
    @Override
    public void getMoneyAndUpdateConsumeMoney(ConsumeService consumeService, ConsumeStatisEntry entry, Date preDay) throws Exception{
        // 1.查询有效规则记录
        Integer cuserId = entry.getCuserId();
        Integer interfaceId = entry.getInterfaceId();
        String interfaceType = entry.getInterfaceType();
        if(null == interfaceId){
            if(!StringUtils.isEmpty(interfaceType)){
                interfaceId = linkService.getInterfaceIdByType(interfaceType);
            }else{
                throw new MyException("接口类型不能为null", HttpServletResponse.SC_NOT_ACCEPTABLE);
            }
        }
        ConsumeHisVo consume = consumeService.getConsume(null, null, cuserId, interfaceId, preDay);
        // 2.计算金额
        RuleVo ruleVo = new RuleVo();
        BeanUtils.copyProperties(consume,ruleVo);
        RulesStrategy rulesStrategy = new RulesStrategy();
        // 2.1.设置标记以及调用量
        ruleVo.setType("consume");
        ruleVo.setCountGet(entry.getCountGet());
        ruleVo.setCountQuery(entry.getCountQuery());
        ruleVo.setCountCharging(entry.getCountCharging());
        Double money = rulesStrategy.getMoney(consume.getFeeFlag(), ruleVo);
        // 3.更新统计的金额
        this.updateConsumeMoney(entry.getCuserId(), interfaceType, GeoDateUtils.getDateStr(preDay, GeoDateUtils.DATE_FORMAT2), money);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getMoneyAndUpdateConsumeMoney(ConsumeService consumeService, List<ConsumeStatisEntry> consumeStatisList, Date preDay) throws Exception {
        for (ConsumeStatisEntry entry : consumeStatisList) {
            // 策略工厂计算消耗金额并更新到mysql
            this.getMoneyAndUpdateConsumeMoney(consumeService, entry, preDay);
        }
    }

    /**
     * 添加分页功能
     * @param obj
     */
    private void insertPage(ParamsConsume obj){
        Integer pageNum = obj.getPageNum();
        Integer pageSize = obj.getPageSize();
        String orderBy = obj.getOrderBy();
        if(null != pageNum && null != pageSize){
            PageHelper.startPage(pageNum,pageSize);
        }
        if(!StringUtils.isEmpty(orderBy)){
            PageHelper.orderBy(orderBy);
        }
    }

}
